/*
*
*
* android -> ohos types wrapper
*
*
*/
#ifndef _UTILS_WRAPPER_H_
#define _UTILS_WRAPPER_H_

#include <string>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include "log.h"
#include <errno.h>
#include "LogWrapper.h"
#include "BacktraceWrapper.h"
#include "LogWrapper_c.h"
namespace OHOS {


typedef enum android_LogPriority {
  /** For internal use only.  */
  ANDROID_LOG_UNKNOWN = 0,
  /** The default priority, for internal use only.  */
  ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
  /** Verbose logging. Should typically be disabled for a release apk. */
  ANDROID_LOG_VERBOSE,
  /** Debug logging. Should typically be disabled for a release apk. */
  ANDROID_LOG_DEBUG,
  /** Informational logging. Should typically be disabled for a release apk. */
  ANDROID_LOG_INFO,
  /** Warning logging. For use with recoverable failures. */
  ANDROID_LOG_WARN,
  /** Error logging. For use with unrecoverable failures. */
  ANDROID_LOG_ERROR,
  /** Fatal logging. For use when aborting. */
  ANDROID_LOG_FATAL,
  /** For internal use only.  */
  ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
} android_LogPriority;

#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
/*
 * Log a fatal error.  If the given condition fails, this stops program
 * execution like a normal assertion, but also generating the given message.
 * It is NOT stripped from release builds.  Note that the condition test
 * is -inverted- from the normal assert() semantics.
 */
#ifndef LOG_ALWAYS_FATAL_IF
#define LOG_ALWAYS_FATAL_IF(cond, ...) \
    ( (CONDITION(cond)) \
    ? ((void)HILOG_ERROR(LOG_CORE,  ##__VA_ARGS__)) \
    : (void)0 )
#endif

#ifndef LOG_FATAL_IF
#define LOG_FATAL_IF(cond, ...) \
    ( (CONDITION(cond)) \
    ? ((void)HILOG_ERROR(LOG_CORE,  ##__VA_ARGS__)) \
    : (void)0 )
#endif

#ifndef LOG_ALWAYS_FATAL
#define LOG_ALWAYS_FATAL(...) \
    ( ((void)HILOG_ERROR(LOG_CORE,  ##__VA_ARGS__)) )
#endif


#define LITERAL_TO_STRING_INTERNAL(x)    #x
#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)

// allow to use CHECK_OP from android-base/logging.h
// TODO: longterm replace this with android-base/logging.h, but there are some nuances, e.g.
// android-base CHECK_OP requires a copy constructor, whereas we don't.
#ifndef CHECK_OP

#define CHECK(condition)                                \
    LOG_ALWAYS_FATAL_IF(                                \
            !(condition),                               \
            "%s",                                       \
            __FILE__ ":" LITERAL_TO_STRING(__LINE__)    \
            " CHECK(" #condition ") failed.")

#define CHECK_OP(x,y,suffix,op)                                         \
    do {                                                                \
        const auto &a = x;                                              \
        const auto &b = y;                                              \
        if (!(a op b)) {                                                \
            std::string ___full =                                           \
                __FILE__ ":" LITERAL_TO_STRING(__LINE__)                \
                    " CHECK_" #suffix "( " #x "," #y ") failed: ";      \
            LOG_ALWAYS_FATAL("%s", ___full.c_str());                    \
        }                                                               \
    } while (false)

#define CHECK_EQ(x,y)   CHECK_OP(x,y,EQ,==)
#define CHECK_NE(x,y)   CHECK_OP(x,y,NE,!=)
#define CHECK_LE(x,y)   CHECK_OP(x,y,LE,<=)
#define CHECK_LT(x,y)   CHECK_OP(x,y,LT,<)
#define CHECK_GE(x,y)   CHECK_OP(x,y,GE,>=)
#define CHECK_GT(x,y)   CHECK_OP(x,y,GT,>)

#endif /*CHECK_OP*/

#ifndef FALLTHROUGH_INTENDED
#define FALLTHROUGH_INTENDED [[clang::fallthrough]]  // NOLINT
#endif
// Changing this definition will cause you a lot of pain.  A majority of
// vendor code defines LIKELY and UNLIKELY this way, and includes
// this header through an indirect path.
#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))

#define WARN_UNUSED __attribute__((warn_unused_result))


#define android_errorWriteLog(tag, subTag) \
    ((void)0)

#ifndef ALOG_ASSERT
#define ALOG_ASSERT(cond, ...) LOG_ALWAYS_FATAL_IF(!(cond), ##__VA_ARGS__)
#endif

inline static int64_t uptimeMillis() {
    struct timespec tv;
    clock_gettime(CLOCK_MONOTONIC, &tv);
    int64_t seconds = tv.tv_sec;
    return seconds * 1000 * 1000 + tv.tv_nsec/1000;
}
} /*end of namespace OHOS*/
#endif  /*end of _UTILS_WRAPPER_H_*/